package com.mxchip.livestarmobile.mobile.ui.call


import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.trello.lifecycle2.android.lifecycle.AndroidLifecycle
import com.trello.rxlifecycle3.LifecycleProvider
import com.mxchip.livestarmobile.R
import com.mxchip.livestarmobile.mobile.constant.RxConstant
import com.mxchip.livestarmobile.mobile.repository.RoomClientRepository
import com.mxchip.livestarmobile.mobile.state.SystemData
import com.mxchip.livestarmobile.mobile.util.Log.FileLog
import com.mxchip.livestarmobile.mobile.util.RingtoneManagement.LocalRingManagement
import com.mxchip.livestarmobile.mobile.util.RxBus.RxBus
import com.mxchip.livestarmobile.mobile.util.RxBus.RxSchedulersHelper
import com.videohigh.hxb.roomclient.event.HangupEvent
import com.videohigh.hxb.roomclient.event.InvitationEvent
import com.mxchip.livestarmobile.mobile.base.toast
import com.mxchip.livestarmobile.mobile.state.AppConstant
import com.orhanobut.hawk.Hawk
import com.videohigh.hxb.roomclient.event.EnterEvent
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.fragment_red.*
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit

class RedFragment : Fragment() {

    private val provider: LifecycleProvider<Lifecycle.Event> = AndroidLifecycle.createLifecycleProvider(this)

    private val dbyViewModel by activityViewModels<DbyViewModel>()
    private val screenViewModel by activityViewModels<ScreenViewModel>()
    private val roomViewModel by activityViewModels<RoomViewModel>()

    private val redViewModel by viewModels<RedViewModel>()

    private val args: RedFragmentArgs by navArgs()

    private lateinit var invitationEvent: InvitationEvent

    private lateinit var hangupEventObservable: Observable<HangupEvent>
    private val compositeDisposable = CompositeDisposable()

    private val logger = FileLog.getLogger(RedFragment::class.java)
    private lateinit var enterEventObservable: Observable<EnterEvent>
    val ownNumber by lazy{
         Hawk.get(AppConstant.SP_LUXX_NUMBER) as String
    }
    var currentPlatform = false
    override fun onDestroyView() {
        super.onDestroyView()
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_red, container, false)
    }

    @SuppressLint("CheckResult")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        invitationEvent = args.invitationEvent

        // 拨号方主动挂断
        hangupEventObservable = RxBus.get().register(RxConstant.HANGUP_EVENT, HangupEvent::class.java)
        hangupEventObservable.compose(provider.bindToLifecycle()).compose(RxSchedulersHelper.io_main())
                .subscribe(::onHangup) { error -> error.printStackTrace() }

        //主叫收到被叫的 接听/挂断 消息
        enterEventObservable = RxBus.get().register(RxConstant.ENTER_EVENT, EnterEvent::class.java)
        enterEventObservable.compose(provider.bindToLifecycle()).compose(RxSchedulersHelper.io_main())
                .subscribe(::onEnter) { error -> error.printStackTrace() }
        Log.e("RedFragment", "invitationEvent $invitationEvent")

        val roomId = invitationEvent.callContext.roomId
        val channelId = invitationEvent.callContext.channelId
        val callIndex = invitationEvent.callContext.callIndex

        val callId = "${roomId}:${channelId}:${callIndex}"

        roomViewModel.setRoomType(RoomViewModel.RoomType.valueOf(invitationEvent.callType))
        roomViewModel.setRoomId(roomId)
        roomViewModel.setChannelId(channelId)
        roomViewModel.setCallIndex(callIndex)


        val fromTermNumber = "${invitationEvent.from.roomId}T${invitationEvent.from.termId}"
        roomViewModel.onJoinRoom(fromTermNumber)

        invitationEvent.invitationNumbers.forEach {
            roomViewModel.onJoinRoom("${it.roomId}T${it.termId}")
        }

        Log.e("RedFragment", "roomViewModel.sessionsCall: ${roomViewModel.sessionsCall.value?.toTypedArray()?.contentToString()}")

        // TODO: 回调数据加入邀请者ID
        val inviterTermId: String = invitationEvent.from.termId

        val sessionsJoin = roomViewModel.sessionsJoin.value

        if (!sessionsJoin.isNullOrEmpty() && sessionsJoin.size > 1) {
            head_portrait.setImageResource(R.drawable.if_icon_group_filled)
            user_name.text = String.format(getString(R.string.invite_you_meetings), inviterTermId.trimStart('0'))
            val join = roomViewModel.getTermIdsAll().joinToString(",") { it.trimStart('0') }
            phone_state.text = getString(R.string.other_participants) + join
        } else {
            head_portrait.setImageResource(R.drawable.if_icon_user)
            user_name.text = String.format("%s", inviterTermId.trimStart('0'))
            phone_state.text = getString(R.string.invite_you_meeting)
        }

        dbyViewModel.videoResInitFinish.observe(viewLifecycleOwner, Observer { it ->
            lifecycleScope.launch {
                if (SystemData.autoAnswer && it) {
                    val nextInt = Random().nextInt(2000)
                    delay(nextInt.toLong() + 1000)
                    reqAccept()
                }
            }
        })

        dbyViewModel.join(callId)
        startPlayLocalRing()

        button_accept.setOnClickListener {
            // stopPlayLocalRing()
            redViewModel.insertCallLog(invitationEvent.from.termId, "1")
            reqAccept()
        }

        button_reject.setOnClickListener {
            Log.e("RedFragment", "onRejectClick")
            redViewModel.insertCallLog(invitationEvent.from.termId, "3")
            stopPlayLocalRing()
            reqReject()
            dbyViewModel.join(null)
        }

        lifecycleScope.launch {
            delay(30 * 1000)
            timeout(0)
        }

        roomViewModel.sessionsAll.observe(viewLifecycleOwner, Observer {

            Log.e("RedFragment", "sessionsAll aa $it")

            if (it.contains(fromTermNumber)) {
                return@Observer
            }

            lifecycleScope.launch {
                toast("对方已挂断")
                delay(1000)
                logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                        " roomViewModel.sessionsAll not contains(fromTermNumber) reqHangup")
                reqHangup()
            }
        })


    }


    override fun onDestroy() {
        super.onDestroy()
        stopPlayLocalRing()
        RxBus.get().unregister(RxConstant.ENTER_EVENT, enterEventObservable)
        RxBus.get().unregister(RxConstant.HANGUP_EVENT, hangupEventObservable)
        compositeDisposable.clear()
    }

    private fun startPlayLocalRing() {
        compositeDisposable.add(Observable.interval(0, 0, TimeUnit.MILLISECONDS)
                .compose(RxSchedulersHelper.io())
                .take(1)
                .subscribe { aLong: Long? -> LocalRingManagement.getInstance().playMusic(R.raw.called, context) })
    }

    private fun stopPlayLocalRing() {
        if (LocalRingManagement.getInstance().isPlaying) {
            LocalRingManagement.getInstance().stop()
        }
    }

    private fun timeout(time: Long) {

        Log.e("RedFragment", "timeout $time")

        redViewModel.insertCallLog(invitationEvent.from.termId, "3")
        reqTimeout()
    }


    private fun reqAccept() {
        currentPlatform = true
        roomViewModel.sessionsAll.removeObservers(viewLifecycleOwner)

        stopPlayLocalRing()
        logger.info(SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.CHINA).format(Date()) + "RedFragment::reqAccept: RoomClientRepository.acceptCall")

        val roomId = roomViewModel.roomId.value!!
        val channelId = roomViewModel.channelId.value!!
        val callIndex = roomViewModel.callIndex.value!!

        RoomClientRepository.enterChannel(0, roomId, channelId, callIndex) { resp ->

            if (resp.result != 0) {
                lifecycleScope.launch {
                    toast("错误代码: ${resp.errorcode}")
                }
                return@enterChannel
            }

            Log.e("RedFragment", "callback enterChannel $resp")

            lifecycleScope.launch {
                Log.e("RedFragment", "callback enterChannel ${resp.terms}")

                roomViewModel.onStartCallRoom("${SystemData.roomId()}T${SystemData.userId()}")

                resp.terms.filter {
                    !(it.roomId == SystemData.roomId() && it.termId == SystemData.userId())
                }.forEach {

                    val fromTermNumber = "${it.roomId}T${it.termId}"

                    roomViewModel.onStartCallRoom(fromTermNumber)

                    Log.e("RedFragment", "callback enterChannel $it, $fromTermNumber")
                    it.deviceNames?.forEach { deviceName ->

                        Log.e("RedFragment", "roomViewModel.addAVDevice $fromTermNumber,$deviceName")
                        roomViewModel.addAVDevice(AVDevice(fromTermNumber, deviceName))
                    }
                }

                dbyViewModel.enterAfterJoined()
                screenViewModel.enterAfterJoined()
                val action = RedFragmentDirections.actionRedFragmentToCallControlFragment()
                Log.e("RedFragment", "  findNavController().navigate")
                findNavController().navigate(action)
            }

        }

    }

    private fun reqReject() {
        logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                " reqReject reqHangup")
        reqHangup()
    }

    private fun reqTimeout() {
        logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                " reqTimeout reqHangup")
        reqHangup()
    }

    private fun reqHangup() {
        val roomId = roomViewModel.roomId.value
        val channelId = roomViewModel.channelId.value
        val callIndex = roomViewModel.callIndex.value
        stopPlayLocalRing()
        if (!roomId.isNullOrBlank() && !channelId.isNullOrBlank() && !callIndex.isNullOrBlank()) {
            RoomClientRepository.hangup(roomId, channelId, callIndex)
        }
        dbyViewModel.join(null)
    }


    private fun onHangup(event: HangupEvent) {
        Log.e("RedFragment", "respRelease: $event")
        val termNumber = "${event.from.roomId}T${event.from.termId}"
        roomViewModel.onLeaveRoom(termNumber)
    }

    private fun onEnter(event: EnterEvent) {
        //TODO 待优化:从event中获取平台信息,比对是否和当前平台一样,来决定是否执行挂断操作
        if (!currentPlatform && event.from.termId == ownNumber) {
            Log.d(TAG, "onEnter: reqHangup")
            reqHangup()
        }
    }

    private val TAG = "RedFragment"
}
